package com.sugon.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.dao.MaterialRecordDao;
import com.sugon.dao.SparePartDao;
import com.sugon.dao.SparePartTransactionRecordDao;
import com.sugon.dao.SpareStorePosDao;
import com.sugon.entity.SparePartEntity;
import com.sugon.entity.SpareStorePosEntity;
import com.sugon.entity.StoreHouseEntity;
import com.sugon.modules.base.consts.StoreHouseType;
import com.sugon.service.SpareStorePosService;
import com.sugon.service.StoreHouseService;
import com.sugon.service.SysConfigService;
import com.sugon.utils.Constant;
import com.sugon.utils.excel.ExcelImport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 备件仓库位置关联 用于存储备件位置以及数量Service实现类
 *
 * @author sugon
 * @date 2020-03-09 11:31:06
 */
@Service("spareStorePosService")
public class SpareStorePosServiceImpl implements SpareStorePosService {

    @Autowired
    private SpareStorePosDao spareStorePosDao;
    @Autowired
    private StoreHouseService storeHouseService;
    @Autowired
    private SparePartDao sparePartDao;
    @Autowired
    private MaterialRecordDao materialRecordDao;
    @Resource
    private SparePartTransactionRecordDao transactionRecordDao;
    @Resource
    private SysConfigService configService;

    @Override
    public SpareStorePosEntity queryObject(String id) {
        return spareStorePosDao.queryObject(id);
    }

    @Override
    public List<SpareStorePosEntity> queryList(Map<String, Object> map) {
        return spareStorePosDao.queryList(map);
    }

    @Override
    public int queryTotal(Map<String, Object> map) {
        return spareStorePosDao.queryTotal(map);
    }

    @Override
    public int save(SpareStorePosEntity spareStorePos) {
        if (StrUtil.isEmpty(spareStorePos.getId())) {
            spareStorePos.setId(RandomUtil.randomString(32));
        }
        spareStorePos.setLocNum(0);
        spareStorePos.setDelFlag(Constant.IS_NOT_DEL_INT);
        spareStorePos.setCreateDate(DateUtil.date());
        return spareStorePosDao.save(spareStorePos);
    }

    @Override
    public SpareStorePosEntity queryByPosition(String storeId, String position, String spareCode) {
        Map<String, Object> param = new HashMap<>(3);
        param.put("storeId", storeId);
        param.put("postion", position);
        param.put("partCode", spareCode);
        List<SpareStorePosEntity> spareStorePosList = spareStorePosDao.queryList(param);
        return CollectionUtil.isNotEmpty(spareStorePosList) ? spareStorePosList.get(0) : null;
    }

    @Override
    public int update(SpareStorePosEntity spareStorePos) {
        return spareStorePosDao.update(spareStorePos);
    }

    @Override
    public int delete(String id) {
        return spareStorePosDao.delete(id);
    }

    @Override
    public int deleteBatch(String[] ids) {
        int rows = 0;
        for (String posId : ids) {
            SpareStorePosEntity spareStorePosEntity = queryObject(posId);
            if (spareStorePosEntity == null) {
                continue;
            }
            int delNum = delete(posId);
            if (delNum > 0) {
                rows += delNum;
                // 实时更新设备库存数
                sparePartDao.realtimeUpdateStock(spareStorePosEntity.getSpareCode());
            }
        }
        return rows;
    }

    @Override
    public SpareStorePosEntity queryOrCreateIfNotExists(String storeId, String position, String spareCode, String spareId) {
        SpareStorePosEntity spareStorePos = queryByPosition(storeId, position, spareCode);
        if (spareStorePos == null) {
            spareStorePos = new SpareStorePosEntity();
            spareStorePos.setStoreId(storeId);
            // 设置库位类型
            StoreHouseEntity storeHouse = storeHouseService.queryObject(storeId);
            Assert.notNull(storeHouse);
            spareStorePos.setPosType(NumberUtil.equals(StoreHouseType.ERP, storeHouse.getStoreType()) ? "ERP" : null);
            spareStorePos.setPostion(position);
            spareStorePos.setSpareCode(spareCode);
            spareStorePos.setSpareId(spareId);
            spareStorePos.setStoreNum(0);
            spareStorePos.setInitNum(0);
            save(spareStorePos);
        }
        return spareStorePos;
    }

    @Override
    public synchronized int realtimeUpdateStorePosStock(String posId) {
        // 获取当前的备件位置信息
        SpareStorePosEntity spareStorePos = queryObject(posId);
        Assert.notNull(spareStorePos);
        /*
            由于ERP库位的特殊性似的在计算事务数和冻结数时
            只计算[最近一次同步ERP库存时间,至今] 这个时间区间内发生的数据
         */
        // 如果为ERP库位，只计算最近一次同步时间到现在为止的数据
        String startDate = null, endDate = null;
        if ("ERP".equals(spareStorePos.getPosType())) {
            startDate = configService.getErpSynTime();
            endDate = DateUtil.now();
        }
        // 获取[startDate,endDate]时间区间内发生的事务数：正数或者负数都有可能
        int transactionNum = transactionRecordDao.statTransactionNum(posId, startDate, endDate);
        // 货位的库存数 = 初始数 + 事务数
        spareStorePos.setStoreNum(spareStorePos.getInitNum() + transactionNum);
        // 找出startDate,endDate]时间区间内发生的当前库位中未出库/冻结的备件数数
        spareStorePos.setLocNum(materialRecordDao.countUnStockOutSparePartStockNum(posId, startDate, endDate));
        return spareStorePosDao.update(spareStorePos);
    }

    @Override
    public synchronized void lockStockNum(String posId, int num) {
        /*
            获取到备件的库位信息后，
            比较下待锁定的数目是否可以，如果不可以则跑出异常
         */
        SpareStorePosEntity pos = spareStorePosDao.queryObject(posId);
        int storeNum = pos.getStoreNum();
        int locNum = pos.getLocNum();
        // 库位可用数目必须不小于待锁定数目
        Assert.isTrue(storeNum - locNum >= num, "可用库存数不足！");
        locNum = locNum + num;
        pos.setLocNum(locNum);
        update(pos);
    }

    @Override
    public int importE(MultipartFile file) {
        // 获取工场Map
        Map<String, String> factories = storeHouseService.listAll();
        List<String[]> list = ExcelImport.getExcelData(file);
        int count = 0;
        if (CollectionUtil.isNotEmpty(list)) {
            SpareStorePosEntity pos = null;
            SparePartEntity sparePart = null;
            for (int i = 1; i < list.size(); i++) {
                String[] array = list.get(i);
                pos = new SpareStorePosEntity();
                sparePart = sparePartDao.queryByOriginPartCode(array[0]);
                if (sparePart == null) {
                    continue;
                }
                pos.setStoreId(factories.get(array[3]));
                pos.setSpareCode(sparePart.getPartCode());
                pos.setPostion(array[4]);
                pos.setInitNum(Integer.parseInt(array[1]));
                pos.setStoreNum(pos.getInitNum());
                count += save(pos);
            }
        }
        return count;
    }
}
